package com.jilefojing.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jilefojing.beans.data.enums.ResponseEnum;
import com.jilefojing.beans.enums.ItemTypeEnumForSource;
import com.jilefojing.beans.enums.ProgressStatusForSource;
import com.jilefojing.beans.enums.ResolutionEnum;
import com.jilefojing.beans.enums.StatusEnumForPublish;
import com.jilefojing.beans.enums.forattitude.TypeEnumForAttitude;
import com.jilefojing.beans.enums.forrsourceuser.RelationTypeEnumForRSourceUser;
import com.jilefojing.beans.exception.UserContextException;
import com.jilefojing.beans.pojos.EAudio;
import com.jilefojing.beans.pojos.RCategorySource;
import com.jilefojing.beans.pojos.RTagSource;
import com.jilefojing.beans.pojos.Recommend;
import com.jilefojing.beans.pojos.base.BasePo;
import com.jilefojing.beans.pojos.enhanced.EnhancedAttitude;
import com.jilefojing.beans.pojos.enhanced.EnhancedDCategory;
import com.jilefojing.beans.pojos.enhanced.EnhancedEAudio;
import com.jilefojing.beans.pojos.enhanced.EnhancedRFavoriteSource;
import com.jilefojing.beans.pojos.enhanced.EnhancedRSourceUser;
import com.jilefojing.beans.pojos.enhanced.EnhancedRTagSource;
import com.jilefojing.beans.pojos.enhanced.EnhancedStatistics;
import com.jilefojing.beans.pojos.enhanced.EnhancedTag;
import com.jilefojing.beans.pojos.enhanced.EnhancedUser;
import com.jilefojing.beans.pojos.enhanced.base.BaseEnhanced;
import com.jilefojing.beans.query.EAudioQuery;
import com.jilefojing.beans.vo.Order;
import com.jilefojing.beans.vo.Pagination;
import com.jilefojing.beans.vo.PlayTypeForEAudio;
import com.jilefojing.beans.vo.UploadFile;
import com.jilefojing.context.beans.vo.UserContext;
import com.jilefojing.dao.IEAudioDao;
import com.jilefojing.dao.IRCategorySourceDao;
import com.jilefojing.dao.IRTagSourceDao;
import com.jilefojing.dao.IRecommendDao;
import com.jilefojing.dao.IStatisticsDao;
import com.jilefojing.qiniu.beans.enums.BucketEnum;
import com.jilefojing.qiniu.beans.enums.BucketEnum.BucketEnumExtral_SourceEnum;
import com.jilefojing.service.IAttitudeService;
import com.jilefojing.service.IDCategoryService;
import com.jilefojing.service.IEAudioService;
import com.jilefojing.service.IRCategorySourceService;
import com.jilefojing.service.IRFavoriteSourceService;
import com.jilefojing.service.IRSourceCorrelationService;
import com.jilefojing.service.IRSourceUserService;
import com.jilefojing.service.IRTagSourceService;
import com.jilefojing.service.ISourceService;
import com.jilefojing.service.IStatisticsService;
import com.jilefojing.service.ITagService;
import com.jilefojing.service.IUserService;
import com.jilefojing.service.base.impl.BaseService;
import com.jilefojing.util.Detect;
import com.jilefojing.util.PropertyFileUtil;
import com.jilefojing.util.QiniuUtil;

/**
 * 
 * @author 作者 jgshun
 * @date 创建时间 2016年07月19日 13时23分08秒
 */
@Service
public class EAudioService extends BaseService<EAudio> implements IEAudioService {
	@Autowired
	private IEAudioDao eAudioDao;
	@Autowired
	private IStatisticsService statisticsService;
	@Autowired
	private IRSourceUserService rSourceUserService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IAttitudeService attitudeService;
	@Autowired
	private IRFavoriteSourceService rFavoriteSourceService;
	@Autowired
	private IRTagSourceService rTagSourceService;
	@Autowired
	private ITagService tagService;
	@Autowired
	private IRSourceCorrelationService rSourceCorrelationService;
	@Autowired
	private ISourceService sourceService;
	@Autowired
	private IDCategoryService dCategoryService;
	@Autowired
	private IRCategorySourceService rCategorySourceService;
	@Autowired
	private IRCategorySourceDao rCategorySourceDao;
	@Autowired
	private IRTagSourceDao rTagSourceDao;
	@Autowired
	private IStatisticsDao statisticsDao;
	@Autowired
	private IRecommendDao recommendDao;

	@Override
	public Pagination<EnhancedEAudio> getPagination(EAudioQuery eAudioQuery, Pagination<EnhancedEAudio> pagination, UserContext userContext) {
		@SuppressWarnings("unchecked")
		Pagination<EAudio> eAudioPagination = eAudioDao.getPagination(eAudioQuery, pagination.copy());
		pagination.setCount(eAudioPagination.getCount());
		if (!Detect.notEmpty(eAudioPagination.getItems())) {
			return pagination;
		}
		List<EnhancedEAudio> enhancedEAudios = this.convent2Enhanceds(eAudioPagination.getItems());
		this.appendEnhancedCommons(enhancedEAudios, userContext);
		pagination.setItems(enhancedEAudios);
		return pagination;
	}

	@Override
	public List<EnhancedEAudio> convent2Enhanceds(List<? extends BasePo> pos) {
		@SuppressWarnings("unchecked")
		List<EAudio> eAudios = (List<EAudio>) pos;

		List<EnhancedEAudio> enhancedEAudios = new ArrayList<EnhancedEAudio>();
		for (EAudio _EAudio : eAudios) {
			if (Detect.notEmpty(_EAudio.getCoverUrl()) && !_EAudio.getCoverUrl().startsWith(SCHEMA)) {
				_EAudio.setCoverUrl(QiniuUtil.getImagesDomain() + "/" + _EAudio.getCoverUrl());
			} else {
				_EAudio.setCoverUrl(AUDIO_DEFAULT_COVER_URL);
			}

			enhancedEAudios.add(new EnhancedEAudio(_EAudio));
		}

		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (_EnhancedEAudio.getSkey() != null && _EnhancedEAudio.getSkey().length() > 0) {
				List<PlayTypeForEAudio> playTypes = new ArrayList<PlayTypeForEAudio>();
				if (_EnhancedEAudio.getSources() != null && _EnhancedEAudio.getSources().length() > 0) {
					String[] sourceSplits = _EnhancedEAudio.getSources().split(",");
					for (String source : sourceSplits) {
						String[] types = source.split("_");
						ResolutionEnum resolution = ResolutionEnum.getResolutionByTypeAndResolution(types[0], types[1]);

						PlayTypeForEAudio playTypeForEAudio = new PlayTypeForEAudio();
						playTypeForEAudio.setResolution(resolution.getResolution());
						playTypeForEAudio.setType(resolution.getType());

						int _lastI = _EnhancedEAudio.getSkey().lastIndexOf("/");
						String _prefix = _EnhancedEAudio.getSkey().substring(0, _lastI + 1);
						String _suffix = _EnhancedEAudio.getSkey().substring(_lastI + 1);

						StringBuilder urlBud = new StringBuilder();
						urlBud.append(_prefix).append(resolution.getType()).append("/").append(resolution.getResolution()).append("/").append(_suffix);

						playTypeForEAudio.setUrl(QiniuUtil.getAudiosDomain() + urlBud.toString());
						playTypes.add(playTypeForEAudio);
					}
				} else {
					PlayTypeForEAudio playTypeForEAudio = new PlayTypeForEAudio();

					if (!_EnhancedEAudio.getSkey().startsWith(SCHEMA)) {
						playTypeForEAudio.setUrl(QiniuUtil.getAudiosDomain() + _EnhancedEAudio.getSkey());
					} else {
						playTypeForEAudio.setUrl(_EnhancedEAudio.getSkey());
					}

					playTypeForEAudio.setResolution(ResolutionEnum.DEFAULT.getResolution());
					playTypeForEAudio.setType(ResolutionEnum.DEFAULT.getType());
					playTypes.add(playTypeForEAudio);
				}

				_EnhancedEAudio.setPlayTypes(playTypes);
			}
		}
		return enhancedEAudios;
	}

	@Override
	public EnhancedEAudio appendEnhancedStatistics(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedStatistics(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedStatistics(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> audioIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			audioIds.add(_EnhancedEAudio.getId());
		}
		List<EnhancedStatistics> enhancedStatisticses = statisticsService.getEnhancedStatisticses(ItemTypeEnumForSource.AUDIO, audioIds, userContext);

		if (Detect.notEmpty(enhancedStatisticses)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				for (EnhancedStatistics _EnhancedStatistics : enhancedStatisticses) {
					if (_EnhancedStatistics.getEnhancedItem() != null) {
						if (_EnhancedEAudio.getId() == ((EnhancedEAudio) _EnhancedStatistics.getEnhancedItem()).getId()) {
							_EnhancedEAudio.setEnhancedStatistics(_EnhancedStatistics);
							break;
						}
					}
				}
			}
		}
		return enhancedEAudios;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedCommons(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
		@SuppressWarnings("unchecked")
		List<EnhancedEAudio> enhancedEAudios = (List<EnhancedEAudio>) enhancedItems;
		this.appendEnhancedStatistics(enhancedEAudios, userContext);
		this.appendCountCognate(enhancedEAudios, userContext);
		this.appendCountCognatePlaytime(enhancedEAudios, userContext);
		this.appendEnhancedUsers(enhancedEAudios, userContext);
		this.appendEnhancedTags(enhancedEAudios, userContext);

		return enhancedEAudios;
	}

	@Override
	public List<EnhancedEAudio> appendCountCognatePlaytime(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> isEntityIds = new ArrayList<Long>();
		List<Long> notEntityIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (!_EnhancedEAudio.isEntity()) {
				notEntityIds.add(_EnhancedEAudio.getId());
			} else if (_EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
				isEntityIds.add(_EnhancedEAudio.getEnhancedParent().getId());
			} else {
				_EnhancedEAudio.setCountCognate(1);
			}
		}
		if (Detect.notEmpty(isEntityIds)) {
			this.appendCountCognatePlaytime_IsEntity(isEntityIds, enhancedEAudios, userContext);
		}

		if (Detect.notEmpty(notEntityIds)) {
			this.appendCountCognatePlaytime_NotEntityIds(notEntityIds, enhancedEAudios, userContext);
		}
		return enhancedEAudios;
	}

	private void appendCountCognatePlaytime_NotEntityIds(List<Long> notEntityIds, List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eAudioDao.countCognatePlaytimeByParentIds(notEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				if (!_EnhancedEAudio.isEntity()) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEAudio.getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEAudio.setCountCognatePlaytime(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	private void appendCountCognatePlaytime_IsEntity(List<Long> isEntityIds, List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eAudioDao.countCognatePlaytimeByParentIds(isEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEAudio.getEnhancedParent().getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEAudio.setCountCognatePlaytime(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	@Override
	public EnhancedEAudio getEnhanced(long id, UserContext userContext) {
		List<EnhancedEAudio> enhancedEAudios = this.getEnhanceds(Arrays.asList(new Long[] { id }), userContext);
		if (!Detect.notEmpty(enhancedEAudios)) {
			return null;
		}
		return enhancedEAudios.get(0);
	}

	@Override
	public List<EnhancedEAudio> getEnhanceds(List<Long> ids, UserContext userContext) {
		List<EAudio> eAudios = eAudioDao.getListByIds(ids);
		if (!Detect.notEmpty(eAudios)) {
			return null;
		}
		List<EnhancedEAudio> enhancedEAudios = this.convent2Enhanceds(eAudios);
		this.appendEnhancedCommons(enhancedEAudios, userContext);
		return enhancedEAudios;
	}

	@Override
	public List<EnhancedEAudio> getEnhancedsNotAppend(List<Long> ids, UserContext userContext) {
		List<EAudio> eAudios = eAudioDao.getListByIds(ids);
		if (!Detect.notEmpty(eAudios)) {
			return null;
		}
		return this.convent2Enhanceds(eAudios);
	}

	@Override
	public EnhancedEAudio appendEnhancedChildren(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedChildren(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedChildren(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> parentIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (!_EnhancedEAudio.isEntity()) {// 是音频集合
				parentIds.add(_EnhancedEAudio.getId());
			}
		}

		if (Detect.notEmpty(parentIds)) {
			List<EnhancedEAudio> enhancedChildEAudios = this.getEnhancedsByParentIds(parentIds, userContext);
			if (Detect.notEmpty(enhancedChildEAudios)) {
				for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
					if (!_EnhancedEAudio.isEntity()) {
						_EnhancedEAudio.setEnhancedChildren(this.getEnhancedEAudiosForParent(_EnhancedEAudio, enhancedChildEAudios));
					}
				}
			}
		}
		return enhancedEAudios;
	}

	@Override
	public List<EnhancedEAudio> getEnhancedsByParentId(long parentId, UserContext userContext) {
		return this.getEnhancedsByParentIds(Arrays.asList(new Long[] { parentId }), userContext);
	}

	@Override
	public List<EnhancedEAudio> getEnhancedsByParentIds(List<Long> parentIds, UserContext userContext) {
		List<EAudio> eAudios = eAudioDao.getListByParentIds(parentIds);
		if (!Detect.notEmpty(eAudios)) {
			return null;
		}
		List<EnhancedEAudio> enhancedEAudios = this.convent2Enhanceds(eAudios);
		this.appendEnhancedCommons(enhancedEAudios, userContext);
		return enhancedEAudios;
	}

	private List<EnhancedEAudio> getEnhancedEAudiosForParent(EnhancedEAudio enhancedParentEAudio, List<EnhancedEAudio> enhancedChildEAudios) {
		List<EnhancedEAudio> curEnhancedChildEAudios = new ArrayList<EnhancedEAudio>();
		for (EnhancedEAudio _EnhancedChildEAudio : enhancedChildEAudios) {
			if (enhancedParentEAudio.getId() == _EnhancedChildEAudio.getEnhancedParent().getId()) {
				curEnhancedChildEAudios.add(_EnhancedChildEAudio);
			}
		}

		return curEnhancedChildEAudios;
	}

	@Override
	public EnhancedEAudio appendEnhancedParent(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedParent(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedParent(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> parentIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
				parentIds.add(_EnhancedEAudio.getEnhancedParent().getId());
			}
		}
		if (Detect.notEmpty(parentIds)) {
			List<EnhancedEAudio> enhancedParentEAudios = this.getEnhanceds(parentIds, userContext);
			if (Detect.notEmpty(enhancedParentEAudios)) {
				this.appendEnhancedParentEAudios(enhancedEAudios, enhancedParentEAudios, userContext);
			}
		}
		return enhancedEAudios;
	}

	private void appendEnhancedParentEAudios(List<EnhancedEAudio> enhancedEAudios, List<EnhancedEAudio> enhancedParentEAudios, UserContext userContext) {
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
				for (EnhancedEAudio _enhancedParentEAudio : enhancedParentEAudios) {
					if (_EnhancedEAudio.getEnhancedParent().getId() == _enhancedParentEAudio.getId()) {
						_EnhancedEAudio.setEnhancedParent(_enhancedParentEAudio);
						break;
					}
				}
			}
		}
	}

	@Override
	public EnhancedEAudio appendCountCognate(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendCountCognate(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendCountCognate(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> isEntityIds = new ArrayList<Long>();
		List<Long> notEntityIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (!_EnhancedEAudio.isEntity()) {
				notEntityIds.add(_EnhancedEAudio.getId());
			} else if (_EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
				isEntityIds.add(_EnhancedEAudio.getEnhancedParent().getId());
			} else {
				_EnhancedEAudio.setCountCognate(1);
			}
		}
		if (Detect.notEmpty(isEntityIds)) {
			this.appendCountCognate_IsEntity(isEntityIds, enhancedEAudios, userContext);
		}

		if (Detect.notEmpty(notEntityIds)) {
			this.appendCountCognate_NotEntityIds(notEntityIds, enhancedEAudios, userContext);
		}
		return enhancedEAudios;
	}

	private void appendCountCognate_NotEntityIds(List<Long> notEntityIds, List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eAudioDao.countCognatesByParentIds(notEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				if (!_EnhancedEAudio.isEntity()) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEAudio.getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEAudio.setCountCognate(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	private void appendCountCognate_IsEntity(List<Long> isEntityIds, List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eAudioDao.countCognatesByParentIds(isEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEAudio.getEnhancedParent().getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEAudio.setCountCognate(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}
	}

	@Override
	public EnhancedEAudio getEnhancedForActive(long id, UserContext userContext) throws UserContextException {
		EnhancedEAudio enhancedEAudio = this.getEnhanced(id, userContext);
		if (enhancedEAudio == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}

		if (enhancedEAudio.getStatus() != StatusEnumForPublish.ALREADY_RELEASED) {
			throw new UserContextException(ResponseEnum.SOURCE_INVALID);
		}

		if (!enhancedEAudio.isEntity()) {
			// TODO 待优化 如果用户从音频集进来的 就调到用户最后一次看的音频
			List<EnhancedEAudio> enhancedEAudios = this.getEnhancedsByParentId(id, userContext);
			if (!Detect.notEmpty(enhancedEAudios)) {
				throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
			}
			enhancedEAudio = enhancedEAudios.get(0);
		}

		return enhancedEAudio;
	}

	@Override
	public EnhancedEAudio appendEnhancedUsers(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedUsers(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedUsers(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> audioIds = new ArrayList<Long>();
		List<Long> createUserIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			audioIds.add(_EnhancedEAudio.getId());
			createUserIds.add(_EnhancedEAudio.getEnhancedCreateUser().getId());
		}
		List<EnhancedRSourceUser> enhancedRSourceUsers = rSourceUserService.getEnhanceds(ItemTypeEnumForSource.AUDIO, audioIds, userContext);

		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			EnhancedUser owner = null;
			if (Detect.notEmpty(enhancedRSourceUsers)) {
				owner = this.getEnhancedOwnerUser(enhancedRSourceUsers, _EnhancedEAudio);
			}
			if (owner == null) {
				// 默认属于系统用户
				owner = super._ENHANCE_SYSTEM_USER_;
				if (owner == null) {
					owner = userService.getEnhancedUser(PropertyFileUtil.getLongValue("system_user_id"));
					super._ENHANCE_SYSTEM_USER_ = owner;
				}
			}
			_EnhancedEAudio.setEnhancedOwner(owner);
		}

		List<EnhancedUser> enhancedCreateUser = userService.getEnhancedUsers(createUserIds);
		if (Detect.notEmpty(enhancedCreateUser)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				for (EnhancedUser _EnhancedUser : enhancedCreateUser) {
					if (_EnhancedEAudio.getEnhancedCreateUser().getId() == _EnhancedUser.getId()) {
						_EnhancedEAudio.setEnhancedCreateUser(_EnhancedUser);
						break;
					}
				}
			}
		}
		return enhancedEAudios;
	}

	private EnhancedUser getEnhancedOwnerUser(List<EnhancedRSourceUser> enhancedRSourceUsers, EnhancedEAudio enhancedEAudio) {
		for (EnhancedRSourceUser _EnhancedRSourceUser : enhancedRSourceUsers) {
			if (enhancedEAudio.getId() == ((EnhancedEAudio) _EnhancedRSourceUser.getEnhancedItem()).getId() && _EnhancedRSourceUser.getRelationType() == RelationTypeEnumForRSourceUser.OWNER) {
				return _EnhancedRSourceUser.getEnhancedUser();
			}
		}
		return null;
	}

	@Override
	public EnhancedEAudio appendEnhancedAttitudeForUser(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedAttitudeForUser(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedAttitudeForUser(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> audioIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			audioIds.add(_EnhancedEAudio.getId());
		}

		List<EnhancedAttitude> enhancedAttitudes = attitudeService.getEnhancedAttitudesByItemsForUser(ItemTypeEnumForSource.AUDIO, audioIds, TypeEnumForAttitude.PRAISE, userContext);
		if (Detect.notEmpty(enhancedAttitudes)) {
			for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
				for (EnhancedAttitude _EnhancedAttitude : enhancedAttitudes) {
					if (_EnhancedEAudio.getId() == ((EnhancedEAudio) _EnhancedAttitude.getEnhancedItem()).getId()) {
						_EnhancedEAudio.setEnhancedAttitude(_EnhancedAttitude);
						break;
					}
				}
			}
		}
		return enhancedEAudios;
	}

	@Override
	public EnhancedEAudio appendEnhancedRFavoriteSourceForUser(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedRFavoriteSourceForUser(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedRFavoriteSourceForUser(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> audioIds = new ArrayList<Long>();
		List<Long> paretnAudioIds = new ArrayList<Long>();

		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
				paretnAudioIds.add(_EnhancedEAudio.getEnhancedParent().getId());
			} else {
				audioIds.add(_EnhancedEAudio.getId());
			}
		}

		if (Detect.notEmpty(audioIds)) {
			List<EnhancedRFavoriteSource> enhancedRFavoriteSources = rFavoriteSourceService.getEnhancedRFavoriteSourcesByItemsForUser(ItemTypeEnumForSource.AUDIO, audioIds, userContext);
			if (Detect.notEmpty(enhancedRFavoriteSources)) {
				for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
					if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
					} else {
						for (EnhancedRFavoriteSource _EnhancedRFavoriteSource : enhancedRFavoriteSources) {
							if (_EnhancedEAudio.getId() == ((EnhancedEAudio) _EnhancedRFavoriteSource.getEnhancedItem()).getId()) {
								_EnhancedEAudio.setEnhancedRFavoriteSource(_EnhancedRFavoriteSource);
								break;
							}
						}
					}
				}
			}
		}

		if (Detect.notEmpty(paretnAudioIds)) {
			List<EnhancedRFavoriteSource> enhancedRFavoriteSources = rFavoriteSourceService.getEnhancedRFavoriteSourcesByItemsForUser(ItemTypeEnumForSource.AUDIO, paretnAudioIds, userContext);
			if (Detect.notEmpty(enhancedRFavoriteSources)) {
				for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
					if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null && _EnhancedEAudio.getEnhancedParent().getId() > 0) {
						for (EnhancedRFavoriteSource _EnhancedRFavoriteSource : enhancedRFavoriteSources) {
							if (_EnhancedEAudio.getEnhancedParent().getId() == ((EnhancedEAudio) _EnhancedRFavoriteSource.getEnhancedItem()).getId()) {
								_EnhancedEAudio.setEnhancedRFavoriteSource(_EnhancedRFavoriteSource);
								break;
							}
						}
					}
				}
			}
		}
		return enhancedEAudios;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<EnhancedEAudio> appendEnhancedExtralsForUser(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
		this.appendEnhancedAttitudeForUser((List<EnhancedEAudio>) enhancedItems, userContext);
		this.appendEnhancedRFavoriteSourceForUser((List<EnhancedEAudio>) enhancedItems, userContext);
		return (List<EnhancedEAudio>) enhancedItems;

	}

	@Override
	public EnhancedEAudio appendEnhancedTags(EnhancedEAudio enhancedEAudio, UserContext userContext) {
		this.appendEnhancedTags(Arrays.asList(new EnhancedEAudio[] { enhancedEAudio }), userContext);
		return enhancedEAudio;
	}

	@Override
	public List<EnhancedEAudio> appendEnhancedTags(List<EnhancedEAudio> enhancedEAudios, UserContext userContext) {
		List<Long> audioIds = new ArrayList<Long>();
		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			audioIds.add(_EnhancedEAudio.getId());
			if (_EnhancedEAudio.isEntity() && _EnhancedEAudio.getEnhancedParent() != null) {
				audioIds.add(_EnhancedEAudio.getEnhancedParent().getId());
			}
		}

		List<EnhancedRTagSource> enhancedRTagSources = rTagSourceService.getEnhancedRTagSourcesByItems(ItemTypeEnumForSource.AUDIO, audioIds, userContext);
		if (!Detect.notEmpty(enhancedRTagSources)) {
			return enhancedEAudios;
		}
		rTagSourceService.appendEnhancedTags2EnhancedRTagSources(enhancedRTagSources, userContext);

		for (EnhancedEAudio _EnhancedEAudio : enhancedEAudios) {
			_EnhancedEAudio.setEnhancedTags(this.getCurEnhancedTags(_EnhancedEAudio, enhancedRTagSources));
		}
		return enhancedEAudios;
	}

	private List<EnhancedTag> getCurEnhancedTags(EnhancedEAudio enhancedEAudio, List<EnhancedRTagSource> enhancedRTagSources) {
		Set<Long> curTagIds = new HashSet<Long>();
		List<EnhancedTag> curEnhancedTags = new ArrayList<EnhancedTag>();
		for (EnhancedRTagSource _EnhancedRTagSource : enhancedRTagSources) {
			long itemId = _EnhancedRTagSource.getEnhancedItem().getDynamicId();
			if (!curTagIds.contains(_EnhancedRTagSource.getEnhancedTag().getId())) {
				if (itemId == enhancedEAudio.getId()) {
					curEnhancedTags.add(_EnhancedRTagSource.getEnhancedTag());
				}
				if (enhancedEAudio.isEntity() && enhancedEAudio.getEnhancedParent() != null && itemId == enhancedEAudio.getEnhancedParent().getId()) {
					curEnhancedTags.add(_EnhancedRTagSource.getEnhancedTag());
				}
				curTagIds.add(_EnhancedRTagSource.getEnhancedTag().getId());
			}
		}
		return curEnhancedTags;
	}

	@Override
	public Pagination<EnhancedEAudio> getPaginationByCategoryIdsForActive(List<Long> categoryIds, List<ProgressStatusForSource> progressStatuses, Pagination<EnhancedEAudio> pagination,
			UserContext userContext) {
		if (!Detect.notEmpty(pagination.getOrders())) {
			pagination.addOrder(new Order(RCategorySource.COLUMN_SORT, Order.ORDER_DESC));
		}
		@SuppressWarnings("unchecked")
		Pagination<? extends BaseEnhanced> baseEnhancedPagination = sourceService.getPaginationByCategoryIdsForActive(categoryIds,
				Arrays.asList(new ItemTypeEnumForSource[] { ItemTypeEnumForSource.AUDIO }), Arrays.asList(new StatusEnumForPublish[] { StatusEnumForPublish.ALREADY_RELEASED }), progressStatuses,
				pagination.copy(), userContext);
		pagination.setCount(baseEnhancedPagination.getCount());
		if (!Detect.notEmpty(baseEnhancedPagination.getItems())) {
			return pagination;
		}

		pagination.setItems((List<EnhancedEAudio>) baseEnhancedPagination.getItems());
		return pagination;
	}

	@Override
	public Pagination<EnhancedEAudio> getPaginationByTagIdForActive(long tagId, Pagination<EnhancedEAudio> pagination, UserContext userContext) {
		@SuppressWarnings("unchecked")
		Pagination<? extends BaseEnhanced> baseEnhancedPagination = sourceService.getPaginationByTagIds(Arrays.asList(new Long[] { tagId }),
				Arrays.asList(new ItemTypeEnumForSource[] { ItemTypeEnumForSource.AUDIO }), Arrays.asList(new StatusEnumForPublish[] { StatusEnumForPublish.ALREADY_RELEASED }), pagination.copy(),
				userContext);

		pagination.setCount(baseEnhancedPagination.getCount());
		if (!Detect.notEmpty(baseEnhancedPagination.getItems())) {
			return pagination;
		}

		pagination.setItems((List<EnhancedEAudio>) baseEnhancedPagination.getItems());
		return pagination;
	}

	@Override
	public List<EnhancedDCategory> getEnhancedDCategories(UserContext userContext) {
		List<EnhancedDCategory> topEnhancedDCategories = dCategoryService.getEnhancedTopDCategoriesByItemType(ItemTypeEnumForSource.AUDIO, userContext);
		dCategoryService.appendEnhancedChildDCategories2EnhancedDCategories(topEnhancedDCategories, userContext);
		return topEnhancedDCategories;
	}

	@Override
	public EAudio updateCover(long id, UploadFile coverUploadFile, UserContext userContext) throws UserContextException {
		EAudio eAudio = eAudioDao.getById(id);
		Date now = new Date();

		this.checkCoverType(coverUploadFile.getSuffix());

		eAudio.setCoverUrl(QiniuUtil.upload(coverUploadFile, BucketEnum.IMG, BucketEnumExtral_SourceEnum.AUDIO_COVER));
		eAudio.setUpdateTime(now);
		return eAudioDao.updateByPrimaryKey(eAudio);
	}

	private void checkCoverType(String suffix) throws UserContextException {
		List<String> imageSuffixs = Arrays.asList(new String[] { "bmp", "png", "gif", "jpg", "jpeg" });
		suffix = suffix.toLowerCase();
		if (!imageSuffixs.contains(suffix)) {
			throw new UserContextException("[图片格式不支持]");
		}
	}

	private void checkAudioType(String suffix) throws UserContextException {
		List<String> audioSuffixs = Arrays.asList(new String[] { "mp3", "wav", "mp4", "ogg", "acc" });
		suffix = suffix.toLowerCase();
		if (!audioSuffixs.contains(suffix)) {
			throw new UserContextException("[音频格式不支持]");
		}
	}

	@Override
	public EAudio add(EAudio eAudio, UserContext userContext) throws UserContextException {
		Date now = new Date();
		if (!Detect.notEmpty(eAudio.getTitle())) {
			throw new UserContextException("[标题不能为空]");
		} else if (eAudio.getTitle().trim().length() > 50) {
			throw new UserContextException("[标题不能超过50字]");
		}
		if (Detect.notEmpty(eAudio.getSummary()) && eAudio.getSummary().trim().length() > 200) {
			throw new UserContextException("[简介不能超过200字]");
		}
		// if (eAudio.getEntity() == 1 && !Detect.notEmpty(eAudio.getSkey())) {
		// throw new UserContextException("[音频资源不能为空]");
		// }

		if (eAudio.getEntity() == 1 && !Detect.notEmpty(eAudio.getTudouCode())) {
			throw new UserContextException("[土豆代码不能为空]");
		}
		if (!Detect.notEmpty(eAudio.getCoverUrl())) {
			throw new UserContextException("[封面资源不能为空]");
		}
		eAudio.setId(null);
		eAudio.setCreateTime(now);
		eAudio.setUpdateTime(now);
		eAudio.setCreateUser(userContext.getUserId());
		eAudio.setStatus(StatusEnumForPublish.PENDING_RELEASE.getCode());
		eAudio.setProgressStatus(ProgressStatusForSource.SERIALISE.getCode());

		return eAudioDao.saveSelective(eAudio);
	}

	@Override
	public EAudio update(EAudio eAudio, UserContext userContext) throws UserContextException {
		EAudio dbEAudio = eAudioDao.getById(eAudio.getId());
		if (dbEAudio == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}
		if (!Detect.notEmpty(eAudio.getTitle())) {
			throw new UserContextException("[标题不能为空]");
		}
		if (eAudio.getStatus() == null || StatusEnumForPublish.getStatusEnumByCode(eAudio.getStatus()) == null) {
			throw new UserContextException("[状态不能为空/不存在]");
		}

		if (eAudio.getProgressStatus() == null || ProgressStatusForSource.getProgressStatusEnumByCode(eAudio.getProgressStatus()) == null) {
			throw new UserContextException("[进度不能为空/不存在]");
		}

		Date now = new Date();

		dbEAudio.setTitle(eAudio.getTitle());
		dbEAudio.setSort(eAudio.getSort());
		dbEAudio.setPlaytime(eAudio.getPlaytime());
		dbEAudio.setSummary(eAudio.getSummary());
		dbEAudio.setInfo(eAudio.getInfo());
		dbEAudio.setStatus(StatusEnumForPublish.getStatusEnumByCode(eAudio.getStatus()).getCode());
		dbEAudio.setUpdateTime(now);
		dbEAudio.setProgressStatus(eAudio.getProgressStatus());

		if ((dbEAudio.getEntity() == null || dbEAudio.getEntity() == 0) && eAudio.getStatus() == StatusEnumForPublish.ALREADY_RELEASED.getCode()) {
			EnhancedEAudio dbEnhancedEAudio = new EnhancedEAudio(dbEAudio);
			this.appendEnhancedChildren(dbEnhancedEAudio, userContext);
			if (!Detect.notEmpty(dbEnhancedEAudio.getEnhancedChildren())) {
				throw new UserContextException("[此音频集中没有任何音频,不能发布]");
			}
		}

		if (dbEAudio.getEntity() == null || dbEAudio.getEntity() == 0) {// 集合
																		// 关联更新子音频进度
			List<EAudio> dbChildren = eAudioDao.getListByParentId(dbEAudio.getId());
			if (Detect.notEmpty(dbChildren)) {
				List<Long> childIds = new ArrayList<Long>();

				for (EAudio _dbChild : dbChildren) {
					_dbChild.setProgressStatus(dbEAudio.getProgressStatus());
					eAudioDao.updateByPrimaryKey(_dbChild);

					childIds.add(_dbChild.getId());
				}

				List<Recommend> dbRecommends = recommendDao.getListByItems(ItemTypeEnumForSource.AUDIO, childIds);
				if (Detect.notEmpty(dbRecommends)) {
					for (Recommend _Recommend : dbRecommends) {
						_Recommend.setStatus(eAudio.getStatus());
						_Recommend.setProgressStatus(dbEAudio.getProgressStatus());
						_Recommend.setUpdateTime(now);

						recommendDao.updateByPrimaryKeySelective(_Recommend);
					}
				}

				List<RCategorySource> rCategorySources = rCategorySourceDao.getListByItems(ItemTypeEnumForSource.AUDIO, childIds);
				if (Detect.notEmpty(rCategorySources)) {
					for (RCategorySource _RCategorySource : rCategorySources) {
						_RCategorySource.setStatus(dbEAudio.getStatus());
						_RCategorySource.setProgressStatus(dbEAudio.getProgressStatus());
						_RCategorySource.setUpdateTime(now);

						rCategorySourceDao.updateByPrimaryKeySelective(_RCategorySource);
					}
				}

				List<RTagSource> rTagSources = rTagSourceDao.getListByItems(ItemTypeEnumForSource.AUDIO, childIds);
				if (Detect.notEmpty(rTagSources)) {
					for (RTagSource _RTagSource : rTagSources) {
						_RTagSource.setStatus(eAudio.getStatus());
						_RTagSource.setProgressStatus(dbEAudio.getProgressStatus());
						_RTagSource.setUpdateTime(now);

						rTagSourceDao.updateByPrimaryKeySelective(_RTagSource);
					}
				}

			}
		}

		List<RCategorySource> rCategorySources = rCategorySourceDao.getListByItem(ItemTypeEnumForSource.AUDIO, eAudio.getId());
		if (Detect.notEmpty(rCategorySources)) {
			for (RCategorySource _RCategorySource : rCategorySources) {
				_RCategorySource.setStatus(dbEAudio.getStatus());
				_RCategorySource.setProgressStatus(dbEAudio.getProgressStatus());
				_RCategorySource.setUpdateTime(now);

				rCategorySourceDao.updateByPrimaryKeySelective(_RCategorySource);
			}
		}
		List<RTagSource> rTagSources = rTagSourceDao.getListByItem(ItemTypeEnumForSource.AUDIO, eAudio.getId());
		if (Detect.notEmpty(rTagSources)) {
			for (RTagSource _RTagSource : rTagSources) {
				_RTagSource.setStatus(eAudio.getStatus());
				_RTagSource.setProgressStatus(dbEAudio.getProgressStatus());
				_RTagSource.setUpdateTime(now);

				rTagSourceDao.updateByPrimaryKeySelective(_RTagSource);
			}
		}

		List<Recommend> recommends = recommendDao.getListByItem(ItemTypeEnumForSource.AUDIO, eAudio.getId());
		if (Detect.notEmpty(recommends)) {
			for (Recommend _Recommend : recommends) {
				_Recommend.setStatus(eAudio.getStatus());
				_Recommend.setProgressStatus(dbEAudio.getProgressStatus());
				_Recommend.setUpdateTime(now);

				recommendDao.updateByPrimaryKeySelective(_Recommend);
			}
		}

		return eAudioDao.updateByPrimaryKeySelective(dbEAudio);
	}

	@Override
	public EAudio updateRelation(long childId, long parentId, boolean optype, UserContext userContext) throws UserContextException {
		EAudio childEAudio = eAudioDao.getById(childId);
		EAudio parentEAudio = eAudioDao.getById(parentId);
		if (childEAudio == null || parentEAudio == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}
		if (optype) {
			if (childEAudio.getParentId() != null && childEAudio.getParentId() > 0) {
				if (childEAudio.getParentId() == parentId) {
					throw new UserContextException("[已经添加了]");
				} else {
					EnhancedEAudio childEnhancedEAudio = new EnhancedEAudio(childEAudio);
					this.appendEnhancedParent(childEnhancedEAudio, userContext);

					throw new UserContextException("[已配置在(集合id:" + childEnhancedEAudio.getEnhancedParent().getId() + ",标题:" + childEnhancedEAudio.getEnhancedParent().getTitle() + ")音频集合中]");
				}
			}
			childEAudio.setParentId(parentId);
		} else {
			if (childEAudio.getParentId() == null || childEAudio.getParentId() < 1) {
				throw new UserContextException("[子音频不存在集合配置关系]");
			}
			if (childEAudio.getParentId() != null && childEAudio.getParentId() > 0 && childEAudio.getParentId() != parentId) {
				throw new UserContextException("[子音频不属于此集合配置]");
			}
			childEAudio.setParentId(0L);
		}
		return eAudioDao.updateByPrimaryKey(childEAudio);
	}
}
